package contegor.scire.core.queries;

import java.util.Collections;
import java.util.List;

import contegor.scire.core.Connectable;
import contegor.scire.core.Container;
import contegor.scire.core.Id;
import contegor.scire.core.InfiniteSingletonList;
import contegor.scire.core.ReturnPoint;
import contegor.scire.core.ReturnPointAdapter;
import contegor.scire.core.Task;
import contegor.scire.core.TaskId;

/**
 * {@link Query} that filters the result of other queries. This filtering will be lead by a set of {@link Condition}s.
 *
 * @version $Revision$
 * @author  Héctor Cirbián Pousa ($Author$)
 */
public class Filter<I extends Connectable> extends QueryWithDependencies<I,I> {
  private static final long serialVersionUID = -3106868955580402859L;

  private Condition<I> condition;

  public Filter(Condition<I> condition, Query<I> dependencie) {
    super(dependencie);
    this.condition = condition;
  }

  public Filter(Id targetContainerId, Condition<I> condition, Query<I> ... dependencies) {
    super(targetContainerId, dependencies);
    this.condition = condition;
  }

  public void process(Container container) {}

  @Override
  public List<? extends Task<I>> getDependencies() {
    return dependencies;
  }

  @Override
  public List<? extends ReturnPoint<I>> getDependenciesReturnPoints() {
    if (this.dependencies == null)
      return Collections.emptyList();

    ReturnPoint<I> dependenciesReturnPoint = new ReturnPointAdapter<I>() {
      public <Y extends I> void manage(TaskId taskId, Y result) {
        if (Filter.this.condition.eval(result))
          returnPoint.manage(taskId, result);
      }
      public void manage(TaskId taskId, Exception exception) {
        returnPoint.manage(taskId, exception);
      }
    };

    return new InfiniteSingletonList<ReturnPoint<I>>(dependenciesReturnPoint, dependencies.size());
  }
}